﻿


using BJYJ_Admin.Core.Utils.ResultUtils;

namespace BJYJ_Admin.Application.System.Services.User;



[ApiDescriptionSettings("System")]

public class SysMenuService : IDynamicApiController, ITransient
{
    public readonly ISqlSugarClient _db;
    public SysMenuService(ISqlSugarClient db)
    {
        _db = db;
    }

    /// <summary>
    ///  获取菜单列表                      
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取菜单列表")]
    [NoEncrypt]
    public virtual async Task<PageResult<MenuListOutDto>> GetMenuList([FromQuery] MenuSearchDto input)
    {
        RefAsync<int> totalCount = 0;
        var menuQuery = _db.Queryable<SYS_MENU>().
                     WhereIF(!string.IsNullOrWhiteSpace(input.MENUNAME), x => x.MENUNAME.Contains(input.MENUNAME))
                    .WhereIF(input.STATUS.HasValue, x => x.STATUS == input.STATUS)
                    .WhereIF(input.DEPTH.HasValue, x => x.DEPTH == input.DEPTH)
                    .WhereIF(input.PID.HasValue, x => x.PID == input.PID)
                    .OrderBy(x => x.DEPTH, OrderByType.Asc)
                    .OrderBy(x => x.ORDER_NUM, OrderByType.Asc)
                    .Select(outMenu => new MenuListOutDto
                    {
                        ID = outMenu.ID,
                        ICON = outMenu.ICON,
                        MENUNAME = outMenu.MENUNAME,
                        MENULINK = outMenu.MENULINK,
                        PID = outMenu.PID,
                        STATUS = outMenu.STATUS,
                        PARENT_PATH = outMenu.PARENT_PATH,
                        DEPTH = outMenu.DEPTH,
                        ORDER_NUM = outMenu.ORDER_NUM,
                        CREATE_TIME = outMenu.CREATE_TIME,
                        CREATE_BY = outMenu.CREATE_BY,
                        UPDATE_TIME = outMenu.UPDATE_TIME,
                        UPDATE_BY = outMenu.UPDATE_BY
                    });
        // 执行分页查询
        var menuList = await menuQuery.ToPageListAsync(input.page, input.limit, totalCount);

        // 提取当前页所有菜单ID
        var menuIds = menuList.Select(x => (int?)x.ID).ToList();

        // 批量查询哪些菜单有子节点（使用聚合查询优化性能）
        var hasChildrenList = await _db.Queryable<SYS_MENU>()
            .Where(x => menuIds.Contains(x.PID))
            .GroupBy(x => x.PID)
            .Select(x => new { PID = x.PID })
            .ToListAsync();

        // 创建快速查找字典
        var hasChildrenDict = hasChildrenList.ToDictionary(x => x.PID, x => true);

        // 给每个角色设置HasChildren属性
        foreach (var menu in menuList)
        {
            menu.HASCHILDREN = hasChildrenDict.ContainsKey(menu.ID);
        }
        return new PageResult<MenuListOutDto>
        {
            page = input.page,
            limit = input.limit,
            totalcount = totalCount,
            data = menuList
        };
    }
    /// <summary>
    /// 新增菜单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("新增菜单")]
    public virtual async Task AddMenu(MenuInfoInsertDto input)
    {
        var menu = new SYS_MENU
        {
            ICON = input.ICON,
            MENUNAME = input.MENUNAME,
            MENULINK = input.MENULINK,
            PID = input.PID,
            STATUS = input.STATUS,
            PARENT_PATH = input.PARENT_PATH,
            DEPTH = input.DEPTH,
            ORDER_NUM = input.ORDER_NUM,
            CREATE_TIME = DateTime.Now,
            CREATE_BY = App.User?.FindFirstValue("ID")
        };
        await _db.Insertable(menu).ExecuteCommandAsync();
    }
    /// <summary>
    /// 编辑菜单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("编辑菜单")]
    public virtual async Task UpdateMenu(SYS_MENU input)
    {
        input.UPDATE_TIME = DateTime.Now;
        input.UPDATE_BY = App.User?.FindFirstValue("ID");
        var result = await _db.Updateable(input)
                .IgnoreColumns(u => new { u.CREATE_BY, u.CREATE_TIME })
                .ExecuteCommandAsync();
        if (result == 0)
            throw Oops.Oh(ErrorCodeEnum.OP0002);
    }
    /// <summary>
    /// 删除菜单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除菜单")]
    public virtual async Task DeleteMenuByID([FromQuery] MenuInfoIDDto input)
    {

        // 开启事务处理
        var result = await _db.Ado.UseTranAsync(async () =>
        {

            // 1.查询要删除菜单的完整路径
            var menu = await _db.Queryable<SYS_MENU>().Where(x => x.ID == input.ID).FirstAsync();

            // 2.构建精确的路径匹配条件
            var currentMenuFullPath = $"{menu.PARENT_PATH},{menu.ID}";
            var pathPrefix = currentMenuFullPath + ",";  // 子菜单路径前缀
            var directChildPath = currentMenuFullPath;   // 直接子节点路径

            // 3.查询要删除的子菜单ID（精确匹配）
            var menuIds = await _db.Queryable<SYS_MENU>()
                .Where(x => x.PARENT_PATH.StartsWith(pathPrefix)  // 所有后代
                    || x.PARENT_PATH == directChildPath)          // 直接子节点
                .Select(x => (int?)x.ID)
                .ToListAsync();

            // 4.加入当前菜单ID
            menuIds.Add(input.ID);

            // 5. 删除角色菜单关联
            await _db.Deleteable<SYS_ROLE_MENU>()
                   .Where(x => menuIds.Contains(x.MID))
                   .ExecuteCommandAsync();

            // 6. 删除子菜单（使用相同的路径条件）
            await _db.Deleteable<SYS_MENU>()
                .Where(x => x.PARENT_PATH.StartsWith(pathPrefix)
                    || x.PARENT_PATH == directChildPath)
                .ExecuteCommandAsync();

            // 7. 删除当前菜单
            await _db.Deleteable<SYS_MENU>()
                .Where(x => x.ID == input.ID)
                .ExecuteCommandAsync();

        });
        if (!result.IsSuccess)
            throw Oops.Oh(result.ErrorMessage);
    }

    /// <summary>
    /// 菜单详情
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [DisplayName("菜单详情")]
    public virtual async Task<SYS_MENU> GetMenuInfoByID(int id)
    {
        var user = await _db.Queryable<SYS_MENU>().Where(x => x.ID == id).FirstAsync();
        return user;
    }

    /// <summary>
    /// 启用禁用菜单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("启用禁用菜单")]
    public virtual async Task UpdateStatusByID(MenuStatusDto input)
    {
        var ID = App.User?.FindFirstValue("ID");
        var result = await _db.Updateable<SYS_MENU>()
                                .SetColumns(it => it.STATUS == input.STATUS)
                                .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                                .SetColumns(it => it.UPDATE_BY == ID)
                                .Where(it => it.ID == input.ID)
                                .ExecuteCommandAsync();
        if (result == 0)
            throw Oops.Oh(ErrorCodeEnum.OP0000);
    }

}

